<?php
/**
 ***********************************************************************************************************************
 * 数据库操作类
 * 说明：
 * 1）从底层禁止跨数据库操作，杜绝低效sql使用。
 * 2）采用延迟创建连接方式，阻止有些数据库连接创建起来，却没有使用。
 * 3）采用同个数据库操作连接复用模式，减少数据库连接创建。
 * 4）采用MySQLi长连接方式复用连接，减少数据库连接创建。
 * 5）采用智能自动读写分离，阻止开发人员无法明确读写分离造成主库依赖严重问题。
 * 6）采用链式自然的链式写法，程序更容易读懂。
 * 7）提供sql分析器，分析sql是否使用索引等。
 * 8）提供大量快捷方法，简化数据库操作。
 *
 * 示例：
 * 支持链式写法，如：db::table('user')->getAll();
 * 支持SQL分析，db::connect()->test(sql) 分析结果包含是否用到索引、优化简单建议
 ***********************************************************************************************************************
 */
namespace artisan;

use artisan\db\mysqlDriver;

/**
 * Class db
 * @package artisan
 */
class db
{
    /**
     * @var
     */
    private $instances;
    /**
     * 当前数据库连接配置
     * @var
     */
    public $config;
    /**
     * 当前数据库连接是否强制使用主库
     * @var bool
     */
    public $forceMaster = false;
    /**
     * @var string
     */
    private $_table = null;
    /**
     * @var string
     */
    private $_query = null;
    /**
     * @var string
     */
    private $_lastQuery = null;
    /**
     * @var null
     */
    private $_select = null;
    /**
     * @var array
     */
    private $_where = array();
    /**
     * @var array
     */
    private $_orderBy = array();
    /**
     * @var array
     */
    private $_groupBy = array();
    /**
     * @var array
     */
    private $_join;
    /**
     * @var
     */
    private $_joinTbls;
    /**
     * @var
     */
    private $_joinOns;
    /**
     * @var
     */
    private $_joinTypes;

    /**
     * @var string
     */
    private $_limit = '';
    /**
     * @param string $dbAlias
     * @param bool $forceMaster
     * @return db
     */
    public static function connect($dbAlias, $forceMaster = false)
    {

        // 配置检测
        if(empty($dbAlias) || !$config = config::get('db')) {
            logCritical('Empty database config give !', '', 'mysql');
            die('Empty database config give!');
        }
        // 兼容处理
        $dbAlias = strtolower($dbAlias);
        // 当前操作逻辑处理
        if(!isset(artisan::$instance->container['db'][$dbAlias]['instance'])) {
            // 创建新的操作实例
            $instance = new db();
            $instance->config = $config[$dbAlias];
            $instance->forceMaster = $forceMaster;
            // 注册实例到核心
            artisan::$instance->container['db'][$dbAlias]['instance'] = $instance;
        }

        return artisan::$instance->container['db'][$dbAlias]['instance'];
    }

    /**
     * 设置数据表
     * @param string $table
     * @return $this
     */
    public function table($table = '')
    {
        $this->_table = $table;
        return $this;
    }


    /**
     * 插入记录时唯一键冲突时更新字段
     * @param $insertData array
     * @param $updateData array
     * @return array|bool|int|mixed
     */
    public function insertOrUpdate($insertData, $updateData)
    {
        if(empty($this->_table) || empty($insertData) || empty($updateData)) {
            return false;
        }

        // 插入数据
        $keys = '';
        $vals = '';
        foreach ($insertData as $key => $val) {
            if (!is_null($val)) {
                $key = empty($keys) ? "`$key`" : ",`$key`";
                $keys .= $key;
                $val = empty($vals) ? "'" . addslashes($val) . "'" : ",'" . addslashes($val) ."'";
                $vals .= $val;
            }
        }

        // 更新数据
        $vars = '';
        foreach ($updateData as $key => $val) {
            if (!is_null($val)) {
                if (preg_match("`($key)([\s\+\-\*\/\%\w]+)`", $val, $out)) { // 处理 "count = count + 1" 等形式
                    $val = "`" . $out[1] . "`" . $out[2];
                } else {
                    $val = "'" . addslashes($val) . "'";
                }
                $var = empty($vars) ? "`$key`=" . $val : ",`$key`=" . $val;
                // $var = empty($vars) ? "`$key`='" . addslashes($val) . "'" : ",`$key`='" . addslashes($val) . "'";
                $vars .= $var;
            }
        }
        $sql = sprintf("INSERT INTO {$this->_table} (%s) VALUES (%s) ON DUPLICATE KEY UPDATE  %s", $keys, $vals, $vars);
        $this->reset();
        return $this->getResult($sql, 'insupd');
    }

    /**
     * 插入
     * @param $insertData
     * @return bool
     */
    public function insert($insertData)
    {
        $ret = $this->buildInsert($insertData);
        return $this->getResult($ret['sql'], $ret['type']);
    }

    /**
     * 构建插入数组
     * @param $insertData
     * @return array|bool
     */
    private function buildInsert($insertData)
    {
        if(empty($this->_table) || empty($insertData)) {
            return false;
        }

        $field_arr = array();
        $value_arr = array();

        $testData = reset($insertData);
        // 单条写入
        if(!(is_array($testData) && count($testData))) {
            foreach($insertData as $field => $value) {
                $field_arr[] = "`" . $field . "`";
                $value_arr[] = is_null($value) ? 'NULL' : "'" . addslashes($value) . "'";
            }
            $field_str = implode(',', $field_arr);
            $value_str = implode(',', $value_arr);
            return array(
                'type' => 'insert',
                'sql' => "INSERT INTO {$this->_table} ({$field_str}) VALUES ({$value_str})"
            );
        }

        // 批量写入
        $field_tmp = array();
        foreach($insertData as $value) {
            $value_tmp = array();
            foreach($value as $field => $val) {
                if(!in_array($field, $field_tmp)) {
                    $field_tmp[] = $field;
                    $field_arr[] = "`" . $field . "`";
                }
                $value_tmp[] = is_null($val) ? 'NULL' : "'" . addslashes($val) . "'";
            }
            $value_arr[] = ' (' . implode(',', $value_tmp) . ')';
        }
        $field_str = implode(',', $field_arr);
        $value_str = implode(',', $value_arr);

        return array(
            'type' => 'batchInsert',
            'sql' => "INSERT INTO {$this->_table} ({$field_str}) VALUES {$value_str}"
        );
    }


    /**
     * @param array $where
     * @param array $updateData
     * @return array|bool|int|mixed
     */
    public function update($where = array(), $updateData)
    {
        // 输入检测
        if(empty($this->_table) || empty($updateData)) {
            return false;
        }

        // 不允许出现没有条件的危险修改
        if(empty($this->_where) && empty($where)) {
            return false;
        }

        // 拼接条件
        $where = $this->where($where ? $where : $this->_where)->_where();

        $vals = array();
        foreach($updateData as $key => $val) {
            if(is_null($val)) {
                $vals[] = $this->_table . '.' . $key . "=NULL";
            } else {
                $vals[] = $this->_table . '.' . $key . "='" . addslashes($val) . "'";
            }
        }
        $val_str = implode(',', $vals);

        $sql = "UPDATE {$this->_table} SET {$val_str} {$where}";

        $this->reset();
        return $this->getResult($sql, 'update');
    }


    /**
     * 删除
     * @param array $where
     * @return bool
     */
    public function delete($where = array())
    {
        // 不允许出现没有条件的危险删除
        if(empty($this->_table) || (empty($where) && empty($this->_where))) {
            return false;
        }
        // 拼接条件
        $where = $this->where($where ? $where : $this->_where)->_where();
        $sql = "DELETE  FROM {$this->_table} {$where}";
        $this->reset();
        return $this->getResult($sql, 'delete');
    }

    /**
     * 清除表数据
     * @param array $where
     * @return bool
     */
    public function clearTable($tableName='')
    {
        $tableName=$tableName?:$this->_table;
        if(empty($tableName)) {
            return false;
        }
        $sql = "DELETE  FROM {$tableName}";
        $this->reset();
        return $this->getResult($sql, 'delete');
    }


    /**
     * 获取多条数据
     *
     * @param array $where
     * @param string $limit
     * @param string $orderBy
     * @param bool $explain
     * @return array|bool|int|mixed
     */
    public function getAll($where = [], $limit = '', $orderBy = '', $explain = false)
    {
        if($where) {
            $this->where($where);
        }
        if($limit) {
            $this->limit($limit);
        }
        if($orderBy) {
            $this->orderBy($orderBy);
        }
        return $this->get($explain);
    }

    /**
     * 按条件检索一条数据
     * @param array $where
     * @param string $orderBy
     * @param bool $explain 是否分析查询语句
     * @return array|mixed
     */
    public function getOne($where = array(), $orderBy = '', $explain = false)
    {
        if($where) {
            $this->where($where);
        }
        if($orderBy) {
            $this->orderBy($orderBy);
        }
        $ret = $this->limit(1)->get($explain);
        if(!empty($ret) && is_array($ret)) {
            return current($ret);
        }
        return [];
    }

    /**
     * 按条件检索统计数据
     * @param array $where
     * @return int|mixed
     */
    public function count($where = array())
    {
        if(empty($this->_table)) {
            return false;
        }
        if(!empty($where)) {
            $this->where($where);
        }
        $sql = "SELECT count(*) as count_num " . $this->_from() . $this->_join() . $this->_where(). $this->_groupBy() . $this->_orderBy() . $this->_limit();
        $this->reset();
        $ret = $this->getResult($sql, 'select');
        return $ret ? $ret[0]['count_num'] : 0;
    }

    /**
     * int字段加一操作
     * @param $where
     * @param $field
     * @return array|bool
     */
    public function incr($where, $field)
    {
        if(empty($this->_table) || empty($where) || empty($field) || !is_string($field)) {
            return false;
        }

        // 拼接条件
        $where = $this->where($where ? $where : $this->_where)->_where();

        $val_str = $this->_table . '.' . $field . "={$field} + 1 ";

        $sql = "UPDATE {$this->_table} SET {$val_str} {$where}";
        $this->reset();
        return $this->getResult($sql, 'update');
    }

    /**
     * int字段减一操作
     * @param $where
     * @param $field
     * @return array|bool
     */
    public function decr($where, $field)
    {
        if(empty($this->_table) || empty($where) || empty($field) || !is_string($field)) {
            return false;
        }

        // 拼接条件
        $where = $this->where($where ? $where : $this->_where)->_where();

        $val_str = $this->_table . '.' . $field . "={$field} - 1 ";

        $sql = "UPDATE {$this->_table} SET {$val_str} {$where}";
        $this->reset();
        return $this->getResult($sql, 'update');
    }


    /**
     * 联合查询
     * @param string $joinTbl
     * @param string $joinOn
     * @param string $joinType
     * @return $this
     */
    public function join($joinTbl = '', $joinOn = '', $joinType = 'LEFT JOIN')
    {
        if(empty($joinTbl)) {
            return $this;
        }
        $this->_joinTbls[$joinTbl] = $joinTbl;
        $this->_joinTypes[$joinTbl] = $joinType;
        $this->_joinOns[$joinTbl] = $joinOn;
        return $this;
    }

    /**
     * 联合查询条件组织
     * @return string
     */
    private function _join()
    {
        if(empty($this->_joinTbls)) {
            return '';
        }
        $join_str = ' ';
        foreach($this->_joinTbls as $val) {
            $join_str .= $this->_joinTypes[$val] . ' ' . $val . ' ON(' . $this->_joinOns[$val].') ';
        }

        return $join_str . ' ';
    }

    /**
     * 结果集限制
     * @param array $limit
     * @return $this
     */
    public function limit($limit = '')
    {
        $this->_limit = $limit;
        return $this;
    }

    /**
     * 结果集限制组织
     * @return string
     */
    private function _limit()
    {
        if(empty($this->_limit)) {
            return ' ';
        }

        if(is_array($this->_limit) && count($this->_limit) == 2) {
            $ret = ' LIMIT ' . $this->_limit[0] . ',' . $this->_limit[1] . ' ';
        } else {
            $ret =  ' LIMIT ' . intval($this->_limit) . ' ';
        }
        return $ret;
    }

    /**
     * 排序
     * @param string $orderBy
     * @return $this
     */
    public function orderBy($orderBy = '')
    {
        $this->_orderBy = $orderBy;
        return $this;
    }

    /**
     * 排序组织
     * @return string
     */
    private function _orderBy()
    {
        if(empty($this->_orderBy)) {
            return ' ';
        }

        $parts = explode(',', $this->_orderBy);
        $parts_arr = array();
        foreach($parts as $val) {
            $parts_arr[] = preg_match('/[.]/', $val) ? $val : $this->_table . '.' .trim($val);
        }

        $this->_orderBy = '';
        return 'ORDER BY ' . implode(',', $parts_arr) . ' ';
    }


    /**
     * 分组
     * @param string $orderBy
     * @return $this
     */
    public function groupBy($groupBy = '')
    {
        $this->_groupBy = $groupBy;
        return $this;
    }

    /**
     * 分组组织
     * @return string
     */
    private function _groupBy()
    {
        if(empty($this->_groupBy)) {
            return ' ';
        }

        $parts = explode(',', $this->_groupBy);
        $parts_arr = array();
        foreach($parts as $val) {
            $parts_arr[] = preg_match('/[.]/', $val) ? $val : $this->_table . '.' .trim($val);
        }

        return 'GROUP BY ' . implode(',', $parts_arr) . ' ';
    }

    /**
     * 检索字段字符串
     * @param array $select
     * @return $this
     */
    public function select($select = null)
    {
        $select = is_array($select) ? implode(',', $select) : $select;
        $this->_select = $select;
        return $this;
    }

    /**
     * @return string
     */
    private function _select()
    {
        if(empty($this->_select)) {
            return 'SELECT ' . $this->_table . '.* ';
        }
        $arr  = explode(',', $this->_select);
        $select = array();
        foreach($arr as $k => $v) {
            $select[$k] = preg_match('/[.]/', $v) ? $v : $this->_table . '.' . $v;
        }

        return 'SELECT ' . implode(',', $select) . ' ';
    }

    /**
     * 检索表组织
     * @return string
     */
    private function _from()
    {
        return 'FROM ' . $this->_table . ' ';
    }


    /**
     * 取数据
     * @param bool $explain 是否开启索引使用分析，仅对查询语句有效
     * @return array|bool|int|mixed
     */
    public function get($explain = false)
    {
        // 拼接sql
        $sql = $this->_select() . $this->_from() . $this->_join() . $this->_where(). $this->_groupBy(). $this->_orderBy() . $this->_limit();
        $this->reset();
        // 仅对查询语句有效
        if($explain === true) {
            return $this->getResult('EXPLAIN ' . $sql, 'select');
        }
        return $this->getResult($sql, 'select');
    }


    /**
     * @param array $where
     * @return $this
     */
    public function where($where = array())
    {
        $this->_where = $where;
        return $this;
    }

    /**
     * where条件拼接
     * @return string
     */
    private function _where()
    {
        if(empty($this->_where)) {
            return '';
        }

        // 拼接条件
        $condition = array();
        foreach($this->_where as $key => $val) {

            // 去除字段前后空格 并且将多个空格转换成一个
            $key = trim(preg_replace('/\s+/', ' ', $key));

            // 将所有条件操作符转换成大写
            $key_arr = explode(' ', $key);
            if(isset($key_arr[1])) {
                $key = $key_arr[0] . ' ' . strtoupper($key_arr[1]);
            }

            // 匹配
            $part_one = preg_match('/\s[>][=]$|\s[<][=]$|\s[>]$|\s[<]$|\s[!][=]$|\s[<][>]$|\sLIKE$|\sIN$/', $key) ? $key : $key . ' =';

            // IN 查询
            if(preg_match('/\sIN$/', $key)) {
                if(is_array($val) && count($val)) {
                    $in = array();
                    foreach($val as $k => $v) {
                        $in[$k] = "'" . addslashes($v) . "'";
                    }
                    $part_two = "(" . implode(',', $in) . ")";
                } else {
                    $part_two = addslashes($val);
                }
            } else {
                // 强制转换成字符
                $val = (string) $val;

                // 处理is null或is not null场景
                $null_val = strtoupper(trim(preg_replace('/\s+/', ' ', $val)));
                if($null_val == 'IS NULL' || $null_val == 'IS NOT NULL') {
                    $part_one = str_replace('=', '', $part_one);
                    $part_two = $null_val;
                } else {
                    $part_two = "'" . addslashes($val) . "'";
                }
            }

            $part_one = preg_match('/[.]/', $part_one) ? $part_one : $this->_table . '.' . $part_one;
            $condition[] = $part_one . ' ' . $part_two;
        }

        $this->_where =  array();
        return 'WHERE ' . implode(' AND ', $condition) . ' ';
    }

    public function isTableExist($tableName,$dbName=''){
        //如果没有dbName，自动解析当前连接的db名
        $dbName=$dbName?:$dbName=$this->config['db'];
        $tableInfo=$this->query("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME ='{$tableName}' and TABLE_SCHEMA='{$dbName}'");
        //logDebug('表名:'.$tableName.' 查询结果:'.json_encode($tableInfo,JSON_UNESCAPED_UNICODE));
        return $tableInfo?true:false;
    }

    public function createTableIfNotExist($tableName,$copyTableName){
        return $this->query("create table if not exists {$tableName} like {$copyTableName}");
    }

    public function dropTableIfExist($tableName=''){
        $tableName=$tableName?:$this->_table;
        // 不允许出现没有条件的危险删除
        if(empty($tableName)) {
            return false;
        }
        return $this->query("drop table if exists {$tableName}");
    }


    /**
     * 直接操作sql
     * @param $sql
     * @param bool $explain 是否开启索引使用分析，仅对查询语句有效
     * @return array|bool|int|mixed
     */

    public function query($sql, $explain = false)
    {
        $this->reset();

        // 仅对查询语句有效
        if($explain === true) {
            return $this->getResult('EXPLAIN ' . $sql, 'select');
        }

        // 分析sql使用的具体方法 暂时只分析select
        $tmp = $sql;
        if(preg_match('/^[\(]*SELECT/', strtoupper(trim(preg_replace('/\s+/', ' ', $tmp))))) {
            return $this->getResult($sql, 'select');
        }

        return $this->getResult($sql);
    }

    /**
     * 事务操作 开始
     */
    public function startTransaction()
    {
        $this->getInstance('write', true)->startTransaction();
    }

    /**
     * 事务操作 提交
     */
    public function commit()
    {
        $this->getInstance('write')->commit();
    }

    /**
     * 事务操作 回滚
     */
    public function rollback()
    {
        $this->getInstance('write')->rollback();
    }


    /**
     * 上一条查询语句
     * @return string
     */
    public function getLastQuery()
    {
        return $this->_lastQuery;
    }

    /**
     * @return string
     */
    public function lastQuery()
    {
        return $this->_lastQuery;
    }

    /**
     * 获取上次插入id
     */
    public function getInsertId()
    {
        return $this->getInstance('write', true)->getInsertId();
    }

    /**
     * @return mixed
     */
    public function insertId()
    {
        return $this->getInstance('write', true)->getInsertId();
    }

    /**
     * 获取操作影响行数
     */
    public function getAffectedRows()
    {
        return $this->getInstance('write', true)->getAffectedRows();
    }

    /**
     * @return int
     */
    public function affectedRows()
    {
        return $this->getInstance('write', true)->getAffectedRows();
    }

    /**
     * 获取上次执行错误
     *
     * @return string
     */
    public function getLastError()
    {
        return $this->getInstance('write', true)->getLastError();
    }

    /**
     * 重置查询条件
     */
    private function reset()
    {
        $this->_table = null;
        $this->_select = null;
        $this->_where = array();
        $this->_join = array();
        $this->_orderBy = array();
        $this->_groupBy = array();
        $this->_joinOns = null;
        $this->_joinTbls = array();
        $this->_joinTypes = null;
        $this->_query = null;
        $this->count = 0;
        $this->_limit = 0;
    }

    /**
     * 获取执行结果
     * @param string $sql
     * @param string $method
     * @return array|bool|int|mixed
     * @TODO 优化返回
     * 2016.1.13日重新优化 复用连接 修正BUG
     */
    private function getResult($sql, $method = '')
    {
//        logDebug('本次执行sql:'.$sql,'sql');//调试sql
        // 记录上一条查询语句
        $this->_lastQuery = $sql;

        // 写实例如果已经存在 直接复用写实例 否则分析是否使用从库
        $instance = $this->getWriteInstance() ?: $this->getInstance($this->analyseSql($sql));

        // 进行数据库操作，返回结果
        switch($method) {
            // 如果影响行数小于零，返回失败，否则返回插入ID
            case 'insert':
                $instance->query($sql);
                if($instance->getAffectedRows() <= 0) {
                    return false;
                }
                return true;
                break;

            // 返回成功失败
            case 'batchInsert':
                $instance->query($sql);
                return $instance->getAffectedRows() > 0;
                break;

            // 返回执行成功失败
            case 'update':
            case 'delete':
            case 'insupd':
                return $instance->query($sql);
                break;

            // 检索
            case 'select':
                $resource = $instance->query($sql);
                return $instance->fetchArray($resource);
                break;

            // 直接返回结果集
            default:
                return $instance->query($sql);
                //return $instance->fetchArray($instance->query($sql));
                break;

        }
    }

    /**
     * 遍历结果集
     * @param $resourece
     * @return array
     */
    public function fetchArray($resource)
    {
        if(empty($resource)) {
            return array();
        }
        return $this->getInstance('read')->fetchArray($resource);
    }

    /**
     * 主动关闭连接
     */
    public function close()
    {
        if($this->getWriteInstance()) {
            $this->getWriteInstance()->close();
        }
        if($this->getReadInstance()) {
            $this->getReadInstance()->close();
        }
        // 清空所有当前读写实例注册
        $this->instances = [];
    }

    /**
     * 读写分离分析
     * @param $sql
     * @return string
     */
    private function analyseSql($sql)
    {
        if($this->forceMaster === true) {
            return 'write';
        }
        // 匹配读操作
        if(preg_match('/^(select|show)/i', ltrim($sql))) {
            return 'read';
        }

        return 'write';
    }


    /**
     * 获取主库实例 修正问题
     * @return mysqlDriver|false
     */
    private function getWriteInstance()
    {
        if(!empty($this->instances['write'])) {
            return $this->instances['write'];
        }
        return false;
    }

    /**
     * 获取从库实例
     * @return mysqlDriver|false
     */
    private function getReadInstance()
    {
        if(!empty($this->instances['read'])) {
            return $this->instances['read'];
        }
        return false;
    }

    /**
     * 对于事务操作 全部操作主库
     * @param $type
     * @param bool $isTransaction
     * @return mysqlDriver
     */
    private function getInstance($type, $isTransaction = false)
    {
        // 连接已经存在？进行复用
        if(isset($this->instances[$type]) || isset($this->instances['write'])) {
            return isset($this->instances[$type]) ? $this->instances[$type] : $this->instances['write'];
        }

        //**************************************************************************************************************
        // write
        //**************************************************************************************************************
        if($type == 'write' || $isTransaction === true) {
            // 注册 并且返回写实例
            return $this->instances['write'] = $this->createWriteInstance();
        }

        //**************************************************************************************************************
        // read
        //**************************************************************************************************************
        // 如果没有可用从库 直接使用主库
        if(empty($this->config['slaves'])) {
            // 注册 并且返回写实例
            return $this->instances['write'] = $this->createWriteInstance();
        }

        // 处理从库
        $count = 0;
        $slaves = array();
        foreach($this->config['slaves'] as $slave) {
            if(!isset($slave['enable']) || $slave['enable'] == true) {
                $slave['weight'] = empty($slave['weight']) ? 100 : $slave['weight'];
                $slaves[] = $slave;
                $count++;
            }
        }

        // 如果所有从库都被禁用 直接使用主库
        if($count == 0) {
            // 注册 并且返回写实例
            return $this->instances['write'] = $this->createWriteInstance();
        }

        return $this->instances['read'] = $this->createReadInstance($slaves);
    }

    /**
     * 创建读实例
     * @param $slaves
     * @return mysqlDriver
     */
    private function createReadInstance($slaves)
    {
        $weight_sum = 0;
        foreach($slaves as $val) {
            $weight_sum += $val['weight'];
        }

        $roll = rand(1, $weight_sum);
        $tmp = 0;
        $key = 0;
        foreach($slaves as $slave_key => $slave) {
            $min = $tmp;
            $tmp += $slave['weight'];
            $max = $tmp;
            if ($roll > $min && $roll <= $max) {
                $key = $slave_key;
                break;
            }
        }

        return new mysqlDriver(
            $slaves[$key]['host'],
            $slaves[$key]['user'],
            $slaves[$key]['pass'],
            $slaves[$key]['db'],
            $slaves[$key]['port']
        );
    }

    /**
     * 创建写实例
     * @return mysqlDriver
     */
    private function createWriteInstance()
    {
        return new mysqlDriver(
            $this->config['host'],
            $this->config['user'],
            $this->config['pass'],
            $this->config['db'],
            $this->config['port']
        );
    }

}
